﻿using System;
using System.Web;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Text.RegularExpressions;
using System.Text;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;

namespace TrinityAPI.Base.Tools
{
    /// <summary>
    /// HTTP请求操作类
    /// </summary>
    public class HttpHelper
    {
        /// <summary>
        /// http请求
        /// </summary>
        /// <param name="url">地址</param>
        /// <param name="param">请求参数</param>
        /// <param name="method">请求方式(GET/POST)</param>
        /// <param name="contentType">请求内容格式</param>
        /// <param name="timeout">过期时间(单位：毫秒)</param>
        /// <param name="headers">请求头</param>
        /// <param name="proxy">代理设置</param>
        /// <param name="ignoreSSLCheck">忽略SSL安全性检查</param>
        /// <returns>请求页面返回的内容</returns>
        public static string HttpApiRequest(string url, string param = null, string method = null, int timeout = 0, Dictionary<string, string> headers = null, string proxy = null, bool ignoreSSLCheck = true)
        {
            string contentType = null;
            Dictionary<string, string> headerDic = new Dictionary<string, string>();
            if (headers != null && headers.Count > 0)
            {
                foreach (var item in headers)
                {
                    if (item.Key.Equals("content-type", StringComparison.OrdinalIgnoreCase))
                        contentType = item.Value;
                    else
                        headerDic.Add(item.Key, item.Value);
                }
            }
            if (string.IsNullOrWhiteSpace(contentType))
                contentType = "application/json";
            headerDic.Add("Content-Type", contentType);

            return HttpWebRequest(url, param, method, timeout, headerDic, proxy, ignoreSSLCheck);
        }

        /// <summary>
        /// http请求
        /// </summary>
        /// <param name="url">地址</param>
        /// <param name="param">请求参数</param>
        /// <param name="method">请求方式(GET/POST)</param>
        /// <param name="contentType">请求内容格式</param>
        /// <param name="timeout">过期时间(单位：毫秒)</param>
        /// <param name="headers">请求头</param>
        /// <param name="proxy">代理设置</param>
        /// <param name="ignoreSSLCheck">忽略SSL安全性检查</param>
        /// <returns>请求页面返回的内容</returns>
        public static string HttpWebRequest(string url, string param = null, string method = null, int timeout = 0, Dictionary<string, string> headers = null, string proxy = null, bool ignoreSSLCheck = true)
        {
            if (string.IsNullOrWhiteSpace(url))
                throw new ArgumentNullException("url");

            if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
            {
                System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls | System.Net.SecurityProtocolType.Tls11 | System.Net.SecurityProtocolType.Tls12;
                if (ignoreSSLCheck)
                    System.Net.ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
            }
            System.Net.HttpWebRequest req = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(url);
            if (headers != null && headers.Count > 0)
            {
                foreach (var item in headers)
                {
                    if (item.Key.Equals("user-agent", StringComparison.OrdinalIgnoreCase))
                        req.UserAgent = item.Value;
                    else if (item.Key.Equals("content-type", StringComparison.OrdinalIgnoreCase))
                        req.ContentType = item.Value;
                    else if (item.Key.Equals("host", StringComparison.OrdinalIgnoreCase))
                        req.Host = item.Value;
                    else if (item.Key.Equals("accept", StringComparison.OrdinalIgnoreCase))
                        req.Accept = item.Value;
                    else if (item.Key.Equals("referer", StringComparison.OrdinalIgnoreCase))
                        req.Referer = item.Value;
                    else
                        req.Headers[item.Key] = item.Value;
                }
            }
            req.Method = !string.IsNullOrWhiteSpace(method) ? method.ToUpper() : "GET";
            if (req.Method.Equals("POST") && string.IsNullOrWhiteSpace(req.ContentType))
                req.ContentType = "application/x-www-form-urlencoded";
            req.Timeout = timeout > 0 ? timeout : 5000;
            req.ContentLength = 0;
            StreamReader reader = null;
            System.Net.HttpWebResponse resp = null;
            try
            {
                if (!string.IsNullOrWhiteSpace(proxy))
                {
                    if (proxy.ToLower() == "false")
                        req.Proxy = null;
                    else
                    {
                        int port;
                        string[] hostAndPort = proxy.Split(':');
                        if (hostAndPort.Length == 2 && int.TryParse(hostAndPort[1], out port))
                            req.Proxy = new WebProxy(hostAndPort[0], port);
                    }
                }
                if (!string.IsNullOrWhiteSpace(param))
                {
                    byte[] data = Encoding.UTF8.GetBytes(param);
                    req.ContentLength = data.Length;
                    using (Stream stream = req.GetRequestStream())
                    {
                        stream.Write(data, 0, data.Length);     //写入数据
                    }
                }
                resp = (System.Net.HttpWebResponse)req.GetResponse();
                reader = new StreamReader(resp.GetResponseStream(), System.Text.Encoding.UTF8);
                return reader.ReadToEnd();
            }
            catch (System.Threading.ThreadAbortException e)
            {
                System.Threading.Thread.ResetAbort();
                throw e;
            }
            catch (Exception e)
            {
                throw e;
            }
            finally
            {
                if (reader != null)
                    reader.Close();
                if (resp != null)
                    resp.Close();
                req.Abort();
            }
        }

        private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            return true;
        }
    }
}
